﻿using SuperX.Common.Log;
using SuperX.DataService.Abstract;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Timers;

namespace SuperX.DataService
{
    public sealed class NetShortGroup : PLCGroup
    {
        public NetShortGroup(string name, int updateRate, bool active, IPLCDriver plcReader)
        {
            this.Name = name;
            this._updateRate = updateRate;
            this._isActive = active;
            this._plcReader = plcReader;
            this._server = _plcReader.DriverParent;
            this._changedList = new List<int>();
            this._cacheReader = new NetShortCacheReader();
        }

        protected override unsafe void Poll()
        {
            short[] cache = (short[])_cacheReader.Cache;
            int offset = 0;
            try
            {
                foreach (PDUArea area in _rangeList)
                {
                    byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据
                    if (rcvBytes == null || rcvBytes.Length == 0)
                    {
                        offset += (area.Len + 1) / 2;
                        //_plcReader.Connect();
                        continue;
                    }
                    else
                    {
                        int len = rcvBytes.Length / 2;
                        fixed (byte* p1 = rcvBytes)
                        {
                            short* prcv = (short*)p1;
                            int index = area.StartIndex;//index指向_items中的Tag元数据
                            int count = index + area.Count;
                            while (index < count)
                            {
                                IIOTag tag = _items[index];
                                DeviceAddress addr = _items[index].Address;
                                int iShort = addr.CacheIndex;
                                int iShort1 = iShort - offset;
                                if (addr.VarType == DataType.BOOL)
                                {
                                    if (addr.ByteOrder.HasFlag(ByteOrder.Network)) prcv[iShort1] = IPAddress.HostToNetworkOrder(prcv[iShort1]);
                                    int tmp = prcv[iShort1] ^ cache[iShort];
                                    DeviceAddress next = addr;
                                    if (tmp != 0)
                                    {
                                        while (addr.Start == next.Start)
                                        {
                                            var moveBit = next.Bit - area.StartBit; //不能从偏移位算起，如配置X43偏移位是3，实际Bit是0，因此要减去area起始地址的位，才对比每个位是否发生值变化
                                            var a = 1 << moveBit;
                                            var b = tmp & a;
                                            if ((tmp & (1 << moveBit)) > 0) _changedList.Add(index);
                                            if (++index < count)
                                                next = _items[index].Address;
                                            else
                                                break;
                                        }
                                    }
                                    else
                                    {
                                        while (addr.Start == next.Start && ++index < count)
                                        {
                                            next = _items[index].Address;
                                        }
                                    }
                                }
                                else
                                {
                                    if (addr.DataSize <= 2)
                                    {
                                        if (prcv[iShort1] != cache[iShort]) _changedList.Add(index);
                                    }
                                    else
                                    {
                                        int size = addr.DataSize / 2;
                                        for (int i = 0; i < size; i++)
                                        {
                                            if (prcv[iShort1 + i] != cache[iShort + i])
                                            {
                                                _changedList.Add(index);
                                                break;
                                            }
                                        }
                                    }
                                    index++;
                                }
                            }
                            for (int j = 0; j < len; j++)
                            {
                                cache[j + offset] = prcv[j];
                            }//将PLC读取的数据写入到CacheReader中
                        }
                        offset += len;
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Warn($"分组名:{this.FullName}，采集错误，信息：{e.Message}");
            }
        }
    }
}